package cell

import (
	"github.com/treelab/updatecolumn/models"
)

// InstanceType of cell
func InstanceType() int32 {
	return models.Collaborator
}

  getCellValue(cell: Cell) {
    return _.map(cell.groups, (group: any) => group.id);
  }

  setCellValue({ cell, column, action, options, isNewCell }: ICCAction, o: CommonOptions) {
    const newGroups = (action.value as CollaboratorCellValue).groups || [];
    const { type: actionType } = action;
    if (actionType === UpdateAction.SET_VALUE || actionType === UpdateAction.ADD_VALUE) {
      newGroups.forEach((group: string) => {
        const newGroup = o.ormTransaction.nodeFor(UserGroup, { uid: group });
        // newGroup.uid = group;
        cell.groups.withFacet(new OrderFacet({ order: cell.groups.get().length })).add(newGroup);
      });
    } else if (actionType === UpdateAction.REMOVE_VALUE) {
      if (!cell.uid) {
        throw new CellNotExistError('');
      }
      newGroups.forEach((group: string) => {
        if (cell.uid && !isNewCell) {
          o?.delQuads.push(...this.dgraphHelperService.getRemoveEdgeQuads(cell.uid!, Relation.HAS_USER_GROUP, group));
          // manually remove value from groups to make cell value is updated
          remove((cell.groups as any)._data, ({ uid }) => uid === group);
        }
      });
    }
    return this;
  }

  cellValueToSelect({ column, cell, userGroup }: IColumnAndCell) {
    const mapping = userGroup?.mapping || {};
    const collaboratorUserNames = this.getCollaboratorUserNames(cell.groups.get(), mapping);
    const option: any = _.find(column.hasColumnOption.get(), i => collaboratorUserNames.includes(i.name));
    return option;
  }

  cellValueToMultiSelect({ column, cell, userGroup }: IColumnAndCell): any[] {
    const mapping = userGroup?.mapping || {};
    const collaboratorUserNames = this.getCollaboratorUserNames(cell.groups.get(), mapping);
    const options: any = _.filter(column.hasColumnOption.get(), i => collaboratorUserNames.includes(i.name));
    return options;
  }

  cellValueToString({ column, cell, userGroup }: IColumnAndCell, target?: string) {
    const mapping = userGroup?.mapping || {};
    if (target && target === ColumnType.PHONE) {
      return cell.groups
        .get()
        .map((group: any) => {
          const users = group.hasUser.get();
          const userId = users[0]?.uid;
          return mapping[userId!]?.phoneNumber;
        })
        .filter(group => group)
        .join(',');
    } else if (target && target === ColumnType.EMAIL) {
      return cell.groups
        .get()
        .map((group: UserGroup) => {
          const users = group.hasUser.get();
          const userId = users[0]?.uid;
          return mapping[userId!]?.email;
        })
        .filter(group => group)
        .join(',');
    } else {
      return this.getCollaboratorUserNames(
        cell.groups.get().map((group: any) => group),
        mapping,
      ).join(',');
    }
    return '';
  }

  convertCell(
    command: UpdateColumn_v2,
    o: CommonOptions,
    { columnCopy, userGroup }: { columnCopy: Column; userGroup: any },
  ) {
    const { column, columnConfig } = command;
    const { type: toType } = columnConfig;
    const { columnType: fromType } = columnCopy;
    const cells = column.hasCell.get();
    const events = new EventHelper();
    const fromCellHandle = this.instanceFactory.getCellInstance(fromType as ColumnType);
    if (this.needEmptyCell(command)) {
      fromCellHandle.emptyCells(command, cells, false, o);
    }
    if (cells.length) {
      _.forEach(cells, cell => {
        const action = {
          type: UpdateAction.SET_VALUE,
          value: { ...command.columnConfig, type: toType },
        };
        const updateCell = {
          ...command,
          action,
          _metadata: { ...command._metadata, source: Source.SAGA },
        };

        const value = action.value as CollaboratorCellValue;
        value.groups = fromCellHandle.cellValueToCollaborator({ column, cell, userGroup });
        super.upsertCell(cell, { command: updateCell }, { ...o, events });
      });
    }

    o.events.bulkAddEvents(...events);
    return this;
  }

  emptyCells(command: UpdateColumn_v2, cells: readonly Cell[], deleteCells: boolean, o: CommonOptions) {
    if (!deleteCells) {
      _.forEach(cells, cell => {
        o.delQuads.push(...this.dgraphHelperService.getRemoveObjectQuads(cell.uid!, Relation.HAS_USER_GROUP));
      });
    }
    super.emptyCells(command, cells, deleteCells, o);
    return this;
  }

